package com.lumi.max.jnicall;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import com.gurun.base.Logger;
import com.gurun.model.database.AppDatabase;
import com.lumi.max.jnicall.serialoperate.DeviceInfo;
import com.lumi.max.jnicall.serialoperate.SerialReadWrite;

import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class jnicall implements SerialReadWrite.SerialReadWriteMethod {
    static {
        System.loadLibrary("gnustl_shared");
        System.loadLibrary("zigbeeLib");

    }

    Context context;

    //======================================= APP需要自己实现，这里只是 为了做个例子 ===================
    public void loadDeviceInfo(Context context) {
//        SharedPreferences sp = context.getSharedPreferences("zigbee_dev_info", Context.MODE_PRIVATE);
//        SharedPreferences.Editor editor = sp.edit();
//        Map<String, String> map = (Map<String, String>) sp.getAll();
//
//        Iterator<Map.Entry<String, String>> entries = map.entrySet().iterator();
//
//        while (entries.hasNext()) {
//            Map.Entry<String, String> entry = entries.next();
//            String stKey = new String(entry.getKey().toString());
//            int key = (int) Integer.valueOf(stKey).intValue();
//            if (!deviceInfoMap.containsKey(key)) {
//                String st = new String(entry.getValue().toString());
//                deviceInfoMap.put(key, new DeviceInfo(st));
//            }
//            System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
//        }
    }


    public void saveDeviceInfo(Context context) {
//        SharedPreferences sp = context.getSharedPreferences("zigbee_dev_info", Context.MODE_PRIVATE);
//        SharedPreferences.Editor editor = sp.edit();
//        for (Map.Entry<Integer, DeviceInfo> entry : deviceInfoMap.entrySet()) {
//            editor.putString(entry.getKey().toString(), entry.getValue().toString());
//        }
//        editor.commit();
    }

    public static Map<Integer, DeviceInfo> deviceInfoMap = new HashMap<Integer, DeviceInfo>();


    //==============================================================================================
    //==============================================================================================
    //==============================================================================================

    private volatile static jnicall singleton;
    private static SerialReadWrite mSerialReadWrite;
    public static final int readLength = 512;
    byte[] readData;
    char[] readDataToText;
    public static boolean bReadThreadGoing = false;

    private List<NotifyCallback> mCallbackList = new ArrayList<>();

    private jnicall(String type) {
        readData = new byte[readLength];
        readDataToText = new char[readLength];
        mSerialReadWrite = SerialReadWrite.create(type);//PL2303
    }

    //串口初始化，启动dongle
    public void open_dongle(Context context) {
        if (getDevCount() <= 0) {
            iniDevice(context);
            if (getDevCount() > 0) {
                connectFunction(context);
            }
        }
//        Thread.sleep(1000);
        while (!isDeviceOpen()) {
//            Thread.sleep(100,0);
            Log.e("!isDeviceOpen()", "Device not open yet 22322");
        }
        if (!isDeviceOpen()) {
            Log.e("!isDeviceOpen()", "Device not open yet");
//            Thread.sleep(50);
            //Toast.makeText(getApplicati onContext(), "Device not open yet...", Toast.LENGTH_SHORT).show();
        } else {
//            open();
            mSerialReadWrite.setConfig(115200, (byte) 8, (byte) 1, (byte) 0, (byte) 0);
            enableRead(true);
            open();
        }

    }

    private jnicall() {
        readData = new byte[readLength];
        readDataToText = new char[readLength];
        mSerialReadWrite = SerialReadWrite.create("PL2303");//TN147//PL2303
    }

    public static jnicall getJnicall(String dongleType) {
        if (singleton == null) {
            synchronized (jnicall.class) {
                if (singleton == null) {
                    singleton = new jnicall(dongleType);
                }
            }
        }
        return singleton;
    }

    //====================================native interface==========================================
    public native int write(String msg);//发控制命令

    public native void open();//打开zigbee

    public native void allowJoin();//允许zigbee 入网（窗磁要入网）

    public native void disableJoin();

    public native void removeDevice(int short_id, long device_id);//删除子设备

    public native int recvZigbeeData(String data);

    public native int startResendOtaThread();

    //==================================== jni 回调 ================================================
    //接收到dongle的JSON报文后，根据报文内容进行相应处理
    public void onMessage(String data) {
        try {
            JSONObject json = new JSONObject(data);
            String cmd = (String) json.get("cmd");
            if (cmd.equals("zigbee_join")) {
                int short_id = (int) json.get("short_id");
                String sid = (String) json.get("sid");
                String model = (String) json.get("model");
                if (deviceInfoMap.get(short_id) == null) {
                    deviceInfoMap.put(short_id, new DeviceInfo(short_id, sid, model));
                }
            }
        } catch (Exception e) {
            Log.v("EagleTag", "back message:" + e.toString());
        }

        Log.e("GateWay", "接收器发来的数据=======：" + data);
        Message message = new Message();
        message.what = 1;
        message.obj = data;
        mHandler.sendMessage(message);
    }


    public static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
//        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));

        }
        return d;
    }

    private static byte charToByte(char c) {
        return (byte) "0123456789abcdef".indexOf(c);
    }

    //发JSON报文给dongle
    public void onSendDataToDongle(String data) {
        if (data.length() < 1) {
            return;
        }
        Logger.d("onSendDataToDongle:" + data);
        byte[] outData = hexStringToBytes(data);

        //byte[] outData = data.getBytes();
        mSerialReadWrite.writeData(outData);
    }

    public long getDeviceId(int short_id) {
        String sid = AppDatabase.getInstance(context).GateWayDao().querySidByShortId(short_id);
        if (TextUtils.isEmpty(sid)) {
            DeviceInfo deviceInfo = deviceInfoMap.get(short_id);
            if (deviceInfo != null) {
                sid = deviceInfo.device_id;
            }
            if (TextUtils.isEmpty(sid)) {
                sid = "0";
            }
        }
        return Long.parseLong(sid, 16);
    }

    //获取zigbee网络的ID
    public int getShortId(long device_id) {
        int shortId = AppDatabase.getInstance(context).GateWayDao().queryShortIdBySid(String.valueOf(device_id));
        return shortId;
    }

    //根据zigbee网络ID获取zigbee设备类型
    public String getModel(int short_id) { //返回 设备对应的model
        String model = AppDatabase.getInstance(context).GateWayDao().queryModelByShortId(short_id);
        if (TextUtils.isEmpty(model)) {
            DeviceInfo deviceInfo = deviceInfoMap.get(short_id);
            if (deviceInfo != null) {
                model = deviceInfo.model;
            }
            if (TextUtils.isEmpty(model)) {
                model = "unknow";
            }
        }
        Log.d("info", "getModel model======:" + model);
        return model;
    }

    //===================================== 串口读写 ===============================================
    public void registerCallback(NotifyCallback callback) {
        mCallbackList.add(callback);
    }

    public void removeCallback(NotifyCallback callback) {
        mCallbackList.remove(callback);
    }

    public interface NotifyCallback {
        void notifyReadDataCallback(String data);

        void enableReadOk();
    }

    public void changeDeviceType(String s) {
        if (mSerialReadWrite != null) {
            enableRead(false);
            mSerialReadWrite.disconnectFunction();
        }
        mSerialReadWrite = SerialReadWrite.create(s);
    }

    public boolean getUartConifged() {
        return mSerialReadWrite.getUartConfiged();
    }

    public void iniDevice(Context context) {
        this.context = context;
        mSerialReadWrite.iniDevice(context);
    }

    public int getDevCount() {
        return mSerialReadWrite.getDevCount();
    }

    public boolean isDeviceOpen() {
        return mSerialReadWrite.isDeviceOpen();
    }

    public void setConfig(int baudRate, byte dataBit, byte stopBit, byte parity, byte flowControl) {
        mSerialReadWrite.setConfig(baudRate, dataBit, stopBit, parity, flowControl);
    }

    private ReadThread mReadThread = null;

    public void enableRead(boolean flag) {
        bReadThreadGoing = flag;
        mSerialReadWrite.enableRead(flag);
        if (bReadThreadGoing) {
            Log.e("enableRead", "enableRead ok");
            for (jnicall.NotifyCallback callback : mCallbackList) {
                if (callback != null) {
                    callback.enableReadOk();
                }
            }
            if (null == mReadThread) {
                mReadThread = new ReadThread(handler);
                mReadThread.start();
            }
        }
    }

    public void connectFunction(Context context) {
        mSerialReadWrite.connectFunction(context);
    }

    public void disconnectFunction() {
        mSerialReadWrite.disconnectFunction();
    }


    private int MESSAGE_QUIT_READ = 1000;
    //有内存泄漏的风险，后期优化
    final Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            for (jnicall.NotifyCallback callback : mCallbackList) {
                callback.notifyReadDataCallback(msg.obj.toString());
            }

            if (msg.what == MESSAGE_QUIT_READ) {
                mReadThread = null;
            }
        }
    };


    public static Handler mHandler;

    private class ReadThread extends Thread {
        ReadThread(Handler h) {
            mHandler = h;
            this.setPriority(Thread.MIN_PRIORITY);
        }

        @Override
        public void run() {
            Log.d("THREAD TAG", "biu biu -read thread-->>>" + Thread.currentThread().getId());
            while (bReadThreadGoing) {
                try {
//                    Log.e("readThread", "eeeeeeeeeeeeee");
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                }
                String data = mSerialReadWrite.readTask();

                if (data != null && data.length() > 0) {
                    Log.d("info", "to recvZigbeeData data======:" + data);
                    recvZigbeeData(data);
                }
            }

            Message msg = handler.obtainMessage();
            msg.what = MESSAGE_QUIT_READ;
            msg.sendToTarget();
        }
    }
}
